package cn.zzf.algs.note.base.collection.v1;

import edu.princeton.cs.algs4.StdOut;

import java.util.Iterator;
import java.util.Spliterator;
import java.util.function.Consumer;

/**
 * @author GaoFeng
 * @date 2019/11/21 11:06
 */
public class ResizingArrayStack<T>  implements Iterable<T>, Stack<T> {

    private int size;
    private T[] elements;

    @SuppressWarnings("unchecked")
    public ResizingArrayStack() {
        this.size = 0;
        this.elements = (T[]) new Object[1];
    }

    @Override
    public void push(T element) {
        if (size == elements.length) {
            // 扩容
            this.changeCapacity(size * 2);
        }

        elements[size++] = element;
    }

    @SuppressWarnings("unchecked")
    public void changeCapacity(int capacity) {

        // 改变当前数组的容量
        StdOut.println("change capacity" + size + " -> " + capacity);
        T[] newElements = (T[]) new Object[capacity];

        for (int i = 0; i < size; i++) {
             newElements[i] = elements[i];
        }

        this.elements = newElements;

    }

    @Override
    public T pop() {
        if (size == elements.length / 4) {
            this.changeCapacity(elements.length / 2);
        }
        T value = elements[size];
        elements[size--] = null;
        return value;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public Iterator<T> iterator() {
        return new Iterator<T>() {

            /** 当前索引 */
            private int currentIndex = size;

            @Override
            public boolean hasNext() {
                return currentIndex > 0;
            }

            @Override
            public T next() {
                return elements[currentIndex--];
            }

            @Override
            public void remove() {

            }
        };
    }

    @Override
    public void forEach(Consumer<? super T> action) {

    }

    @Override
    public Spliterator<T> spliterator() {
        return null;
    }
}
